#include "ThreadCache.h"
#include "CentralCache.h"

void* ThreadCache::FetchFromCentralCache(size_t index, size_t size)
{
    // .....
    // 慢开始反馈调节算法
	// 1、最开始不会一次向central cache一次批量要太多，因为要太多了可能用不完
	// 2、如果你不要这个size大小内存需求，那么batchNum就会不断增长，直到上限
	// 3、size越大，一次向central cache要的batchNum就越小
	// 4、size越小，一次向central cache要的batchNum就越大

    size_t batchNum = std::min(_freelists[index].MaxSize(), SizeClass::NumMoveSize(size));
    if (_freelists[index].MaxSize() == batchNum)
    {
        _freelists[index].MaxSize() += 1;
    }

    void* start = nullptr;
    void* end = nullptr;

    size_t actualNUm = CentralCache::GetInstance()->FetchRangeObj(start, end, batchNum, size);
    assert(actualNUm >= 1);

    if (actualNUm == 1)
    {
        assert(start == end);
        return start;
    }
    else
    {
        _freelists[index].PushRange(start, end);
        return start;
    }


}


void* ThreadCache::Allocate(size_t size)
{
    assert(size <= MAX_BYTES);
    size_t alignaSize = SizeClass::RoundUp(size); // 对齐后的size大小
    size_t index = SizeClass::Index(size); // 对应的桶的下标

    if (!_freelists[index].Empty())
    {
        return _freelists[index].Pop();
    }
    else
    {
        return FetchFromCentralCache(index, alignaSize);
    }

}




void ThreadCache::Deallocate(void *ptr, size_t size)
{
    assert(ptr);
    assert(size <= MAX_BYTES);

    // 找对应映射的自由链表桶，对象插入进去
    size_t index = SizeClass::Index(size);
    _freelists[index].Push(ptr);
}